﻿namespace BizVal.Contracts
{
    using System;

    public class TriangularLabel
    {
        /// <summary>
        /// Lower value of the Label.
        /// </summary>
        public decimal Lower { get; set; }

        /// <summary>
        /// Modal value of the label
        /// </summary>
        public decimal Modal { get; set; }

        /// <summary>
        /// Higher value of the label
        /// 
        /// </summary>
        public decimal Higher { get; set; }

        /// <summary>
        /// Natural language term that represents the label
        /// </summary>
        public String Term
        {
            get;
            set;
        }

        public int Index
        {
            get;
            set;
        }

        public LabelSet LabelSet { get; set; }

        public TwoTuple Tuple { get; set; }

        /// <summary>
        /// Creates a triangular linguistic label.
        /// </summary>
        /// <param name="lower">Lower value of the label.</param>
        /// <param name="modal">Modal value of the label.</param>
        /// <param name="higher">Higher value of the label.</param>
        public TriangularLabel(decimal lower, decimal modal, decimal higher)
        {
            // if ((a > modal) || (a > higher) || (modal < a) || (modal > higher) || (higher < a) || (higher < modal))
            //    throw new CWException(CWExceptionType.NoLabelSet);

            this.Lower = lower;
            this.Higher = higher;
            this.Modal = modal;
        }



        /// <summary>
        /// Creates a new triangular liguistic labe, assigning a natural language term to it.
        /// </summary>
        /// <param name="a">Lower value of the label</param>
        /// <param name="m">Modal value of the label</param>
        /// <param name="b">Higher value of the label</param>
        /// <param name="term">Natural language term that represents the label.</param>
        public TriangularLabel(decimal a, decimal m, decimal b, string term)
            : this(a, m, b)
        {
            this.Term = term;
        }


        /// <summary>
        /// Triangular belonging function
        /// </summary>
        /// <param name="x">Value to evaluate</param>
        /// <returns>Belonging degree as a value of interval [0,1]</returns>
        public decimal BelongsTo(decimal x)
        {
            decimal ret = 0;
            if ((x <= this.Lower) || (x >= this.Higher))
            {
                ret = 0;
            }
            else if ((x > this.Lower) && (x <= this.Modal))
            {
                ret = (x - this.Lower) / (this.Modal - this.Lower);
            }
            else if ((x > this.Modal) && (x < this.Higher))
            {
                ret = (this.Higher - x) / (this.Higher - this.Modal);
            }
            return ret;
        }

        /// <summary>
        /// Devuelve un valor indicando si una etiqueta es igual a la instancia.
        /// </summary>
        /// <param name="obj">Objeto a comparar</param>
        /// <returns>TRUE si <paramref name="obj"/> es una instancia de TriEtiqueta y su valor es el mismo. FALSE en otro caso</returns>
        public override bool Equals(object obj)
        {
            try
            {
                TriangularLabel b = (TriangularLabel)obj;
                return ((this.Lower == b.Lower) && (this.Modal == b.Modal) && (this.Higher == b.Higher));
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// Convierte la instancia a una cadena de texto.
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return String.Format("{0}({1:F4}, {2:F4}, {3:F4})", this.Term, this.Lower, this.Modal, this.Higher);
        }

        /// <summary>
        /// Devuelve un código hash que representa la instancia.
        /// </summary>
        /// <returns>Código hash</returns>
        public override int GetHashCode()
        {
            string cadenaEtiqueta = String.Format("({0}, {1}, {2})", this.Lower.ToString(), this.Modal.ToString(), this.Higher.ToString());
            return cadenaEtiqueta.GetHashCode();
        }
    }
}

